package com.mlk.rbac.shiro;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.mlk.core.constants.Constant;
import com.mlk.core.util.SpringUtils;
import com.mlk.rbac.mapper.*;
import com.mlk.rbac.po.*;
import com.mlk.rbac.vo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 自定义的shiro Realm
 * 
 * @author xulu
 *
 */
public class ShiroRealm extends AuthorizingRealm {

	/**
	 * 完成认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken utoken = (UsernamePasswordToken) token;
		String username = utoken.getUsername();
		String password = new String(utoken.getPassword());
		// 查询用户
		SysUser user = getSysUserMapper().selectOne(SysUser.builder().username(username).build());
		if (user == null) {
			throw new UnknownAccountException();
		}

		// 比较密码
		if (!StringUtils.equals(password, user.getPassword())) {
			throw new IncorrectCredentialsException();
		}

		// 判断状态
		if (user.getStatus() == Constant.UserStatus.lock) {
			throw new LockedAccountException();
		}

		// 现在认为用户的账号和密码是没有问题的了
		user.setPassword(null);
		SysDept dept = getSysDeptMapper().selectOne(SysDept.builder().id(user.getId()).build());

		// 构造session之中存储的用户对象
		User sessionUser = User.builder().sysUser(user).sysDept(dept).id(String.valueOf(user.getId())).build();

		Session session = SecurityUtils.getSubject().getSession();

		session.setAttribute(Constant.SESSION_USER, sessionUser);

		return new SimpleAuthenticationInfo(sessionUser, password.toCharArray(), this.getClass().getSimpleName());
	}

	/**
	 * 完成用户的授权
	 * @param principals
	 * @return
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		Object principal = principals.getPrimaryPrincipal();
		User user = null;
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		if(principal instanceof  User){
			user = (User) principal;
			// 获取用户的id,进而查询所有的role的desc标识符
			Integer userId = user.getSysUser().getId();
			List<SysRoleUser> sysRoleUsers = getSysUserRoleMapper().selectList(new EntityWrapper<>(SysRoleUser.builder().userId(userId).build()));
			List<Integer> roleIds = sysRoleUsers.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
			if(!CollectionUtils.isEmpty(roleIds)){
				List<SysRole> roles = getSysRoleMapper().selectBatchIds(roleIds);

				simpleAuthorizationInfo.setRoles(roles.stream().map(e->e.getRoleDesc()).collect(Collectors.toSet()));

				// 通过roleIds查询所有关联的权限信息
				List<SysRoleAcl> sysRoleAcls = getRoleAclMapper().selectByRoleIds(roleIds);
				//进而查询所有的权限
				Set<Integer> aclIds = sysRoleAcls.stream().map(e -> e.getAclId()).collect(Collectors.toSet());
				//
				if(!CollectionUtils.isEmpty(aclIds)){
					List<SysAclModule> sysAcls = getSysAclModuleMapper().selectPermissionByAclId(aclIds);
					simpleAuthorizationInfo.setStringPermissions(sysAcls.stream().map(e->e.getAclDesc()).collect(Collectors.toSet()));
				}
			}
		}
		return simpleAuthorizationInfo;
	}

	/**
	 * 获取用户mapper
	 * 
	 * @return
	 */
	private SysUserMapper getSysUserMapper() {
		return SpringUtils.getBean(SysUserMapper.class);
	}

	/**
	 * 获取组织管理mapper
	 * 
	 * @return
	 */
	private SysDeptMapper getSysDeptMapper() {
		return SpringUtils.getBean(SysDeptMapper.class);
	}

	/**
	 * 获取用户角色Mapper
	 * @return
	 */
	private SysUserRoleMapper getSysUserRoleMapper(){

		return SpringUtils.getBean(SysUserRoleMapper.class);
	}

	/**
	 * 获取角色Mapper
	 * @return
	 */
	private SysRoleMapper getSysRoleMapper(){
		return SpringUtils.getBean(SysRoleMapper.class);
	}

	/**
	 * 获取角色权限Mapper
	 * @return
	 */
	private SysRoleAclMapper getRoleAclMapper(){
		return SpringUtils.getBean(SysRoleAclMapper.class);
	}
	
	/**
	 * 获取权限mapper
	 * @return
	 */
	private SysAclModuleMapper getSysAclModuleMapper(){
		return SpringUtils.getBean(SysAclModuleMapper.class);
	}

}
